<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>梦幻西游封妖记录</title>
  <style>
    body {
      font-family: '微软雅黑', Arial, sans-serif;
      background: #f5f5f5;
      margin: 0;
      padding: 0;
      min-height: 100vh;
    }

    .main-flex {
      display: flex;
      justify-content: center;
      align-items: flex-start;
      min-height: 100vh;
      width: 100vw;
      padding-top: 70px;
      max-width: 900px;
      margin: 0 auto;
    }

    #scene-area {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 0;
    }

    .container {
      background: #fff;
      margin-top: 28px;
      border-radius: 14px;
      box-shadow: 0 4px 18px rgba(45, 140, 240, 0.10), 0 1.5px 4px rgba(0, 0, 0, 0.04);
      padding: 12px 14px 12px 14px;
      min-width: 420px;
      max-width: 600px;
      margin-right: 0;
      transition: box-shadow 0.2s, transform 0.2s;
      position: relative;
      overflow-x: auto;
    }

    .container:hover {
      box-shadow: 0 8px 32px rgba(45, 140, 240, 0.16), 0 2px 8px rgba(0, 0, 0, 0.06);
      transform: translateY(-2px) scale(1.02);
    }

    .container h2 {
      font-size: 1.18em;
      margin-bottom: 10px;
      margin-top: 0;
      color: #2d8cf0;
      letter-spacing: 1px;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      gap: 10px;
    }

    .container .scene-level {
      font-size: 0.98em;
      color: #888;
      background: #f0f7ff;
      border-radius: 6px;
      padding: 2px 8px;
      margin-left: 2px;
      font-weight: normal;
    }

    .container .scene-total {
      font-size: 1em;
      color: #52c41a;
      margin-left: auto;
      font-weight: bold;
      background: #f6ffed;
      border-radius: 6px;
      padding: 2px 10px;
    }

    .container table {
      border: 2px solid #2d8cf0;
      border-radius: 10px;
      overflow: hidden;
      border-collapse: collapse;
      font-size: 14px;
      margin-top: 2px;
    }

    .container th,
    .container td {
      padding: 6px 4px;
      text-align: center;
      border: 1px solid #b3d8fd;
    }

    .container th {
      background: #f0f7ff;
      color: #2d8cf0;
      font-weight: 600;
      font-size: 13px;
      padding: 7px 2px;
    }

    .container tr:nth-child(even) td {
      background: #f8fafd;
    }

    .container .btn {
      width: 24px;
      height: 24px;
      font-size: 15px;
      border-radius: 4px;
      margin: 0 1px;
      padding: 0;
    }

    .container .btn.reset {
      width: 38px;
      font-size: 13px;
      margin-left: 2px;
      padding: 0;
      border-radius: 4px;
    }

    .container .count {
      font-size: 1em;
      min-width: 24px;
      display: inline-block;
    }

    .container .monster-name {
      max-width: 160px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      display: inline-block;
      vertical-align: middle;
      text-align: left;
    }

    .side-panel {
      background: #fff;
      margin-top: 40px;
      margin-left: 40px;
      border-radius: 12px;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
      padding: 24px 28px;
      min-width: 260px;
      max-width: 340px;
      word-break: break-all;
      font-size: 15px;
      color: #333;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      overflow-y: auto;
      max-height: 80vh;
    }

    .side-panel h3 {
      margin-top: 0;
      margin-bottom: 12px;
      color: #2d8cf0;
      font-size: 1.1em;
    }

    .export-btn {
      background: #52c41a;
      color: #fff;
      border: none;
      border-radius: 4px;
      padding: 6px 18px;
      font-size: 15px;
      cursor: pointer;
      margin-top: 12px;
      margin-bottom: 8px;
      transition: background 0.2s;
    }

    .export-btn:active {
      background: #237804;
    }

    h2 {
      margin-top: 0;
      margin-bottom: 24px;
      font-size: 1.5em;
      color: #2d8cf0;
      letter-spacing: 2px;
      text-align: left;
    }

    table {
      width: 100%;
      border-collapse: collapse;
    }

    th,
    td {
      padding: 10px 12px;
      text-align: center;
      min-width: 70px;
      white-space: nowrap;
      font-size: 15px;
    }

    th {
      background: #f0f7ff;
      color: #2d8cf0;
      font-weight: bold;
      font-size: 15px;
    }

    tr:nth-child(even) td {
      background: #f8fafd;
    }

    .btn {
      background: #2d8cf0;
      color: #fff;
      border: none;
      border-radius: 4px;
      width: 28px;
      height: 28px;
      font-size: 18px;
      cursor: pointer;
      transition: background 0.2s;
      vertical-align: middle;
      margin: 0 2px;
    }

    .btn:active {
      background: #1766b3;
    }

    .btn.reset {
      width: 48px;
      font-size: 15px;
      background: #ff7875;
      margin-left: 6px;
      padding: 0;
      border-radius: 4px;
      transition: background 0.2s;
    }

    .btn.reset:active {
      background: #d9363e;
    }

    td {
      vertical-align: middle;
    }

    .count {
      font-size: 1.1em;
      min-width: 32px;
      display: inline-block;
    }

    .history-list {
      width: 100%;
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .history-date {
      background: #f0f7ff;
      color: #2d8cf0;
      font-weight: bold;
      padding: 8px 10px;
      border-radius: 6px;
      margin-bottom: 6px;
      cursor: pointer;
      user-select: none;
      display: flex;
      align-items: center;
      justify-content: space-between;
      transition: background 0.2s;
    }

    .history-date:hover {
      background: #e6f4ff;
    }

    .history-content {
      background: #f8fafd;
      border-radius: 0 0 6px 6px;
      margin-bottom: 12px;
      padding: 10px 16px 10px 16px;
      font-size: 14px;
      display: none;
    }

    .history-content.active {
      display: block;
    }

    .monster-row {
      display: flex;
      justify-content: space-between;
      padding: 3px 0;
      border-bottom: 1px dashed #e0e0e0;
    }

    .monster-row:last-child {
      border-bottom: none;
    }

    .scene-title {
      color: #2d8cf0;
      font-size: 15px;
      font-weight: bold;
      margin-bottom: 6px;
      margin-top: 10px;
      border-bottom: 1.5px solid #e6f4ff;
      padding-bottom: 2px;
      letter-spacing: 1px;
      background: linear-gradient(to right, #f0f7ff 60%, transparent 100%);
      border-radius: 4px;
      display: inline-block;
    }

    .arrow {
      font-size: 13px;
      margin-left: 6px;
      transition: transform 0.2s;
    }

    .arrow.open {
      transform: rotate(90deg);
    }

    .scene-selector-btn {
      margin: 0 8px 0 0;
      background: #f0f7ff;
      border: 1px solid #2d8cf0;
      border-radius: 6px;
      padding: 6px 16px;
      cursor: pointer;
      font-size: 15px;
      transition: all 0.2s;
    }

    .scene-selector-btn:hover {
      background: #e6f4ff;
    }

    .scene-selector-btn.active {
      background: #2d8cf0;
      color: #fff;
    }

    .monster-row td:first-child,
    td span.monster-name {
      max-width: 110px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      display: inline-block;
      vertical-align: middle;
    }

    .monster-row-variant {
      background: #fffbe6 !important;
      font-weight: bold;
      color: #d48806;
    }

    .monster-row-variant .monster-name::before {
      content: '★ ';
      color: #faad14;
      font-size: 1em;
      font-weight: bold;
    }

    .monster-avatar {
      width: 32px;
      height: 32px;
      border-radius: 50%;
      object-fit: cover;
      margin-right: 6px;
      background: #f0f0f0;
      border: 1.5px solid #e6f4ff;
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
      display: inline-block;
      vertical-align: middle;
    }

    .monster-row,
    .monster-row-variant,
    td {
      vertical-align: middle !important;
      border-bottom: 2px solid #e0c36b !important;
    }
    tbody tr:hover {
      box-shadow: 0 4px 18px rgba(45,140,240,0.13), 0 1.5px 4px rgba(0,0,0,0.04);
      transform: translateY(-2px) scale(1.02);
      z-index: 2;
      position: relative;
      transition: box-shadow 0.2s, transform 0.2s;
    }

    .monster-cell {
      display: flex;
      align-items: center;
      justify-content: flex-start;
      gap: 6px;
    }
    .monster-row-nine {
      background: #fffbe6 !important;
      color: #d48806 !important;
      border-bottom: 1px dashed #e0e0e0 !important;
    }
    /* 主表格美化 */
    .container .monster-row-variant {
      background: #e6f7ff !important;
      font-weight: bold;
      color: #1766b3 !important;
      font-size: 16px !important;
    }
    .container .monster-row-variant .monster-name {
      display: flex;
      align-items: center;
      font-size: 16px !important;
      font-weight: bold;
    }
    .container .monster-row-variant .monster-name::before {
      content: '★';
      display: inline-block;
      margin-right: 6px;
      color: #ffc700;
      font-size: 22px;
      font-weight: bold;
      filter: drop-shadow(0 0 2px #fff3d1);
    }

    /* 历史数据美化回原样 */
    .history-content .monster-row-variant,
    .history-content .monster-row-variant td {
      background: #e6f7ff !important;
      color: #1766b3 !important;
      font-size: 15px !important;
      font-weight: normal !important;
    }
    .history-content .monster-row-variant .monster-name {
      display: inline-block;
      font-size: 15px !important;
      font-weight: normal !important;
    }
    .history-content .monster-row-variant .monster-name::before {
      content: '★ ';
      color: #faad14;
      font-size: 1em;
      font-weight: bold;
      margin-right: 2px;
      filter: none;
    }
    /* 隐藏降妖谱数量输入框的上下箭头 */
    input[type=number]::-webkit-inner-spin-button,
    input[type=number]::-webkit-outer-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }
    input[type=number] {
      -moz-appearance: textfield;
      text-align: center;
    }
  </style>
</head>

<body onload="updateJsonView(); updateHourlyStats(); updateTimeGapStats(); renderOpLog()">
  <div class="main-flex">
    <div
      style="position:absolute;left:0;right:0;top:0;padding:24px 0 0 0;text-align:center;z-index:2;pointer-events:auto;">
      <div id="scene-selectors"
        style="display:inline-block;background:#fff;border-radius:8px;padding:10px 24px;box-shadow:0 2px 8px rgba(0,0,0,0.08);">
      </div>
    </div>
    <div style="flex:1;display:flex;justify-content:center;">
      <div id="scene-area" style="margin-top:0;"></div>
    </div>
    <div style="display:flex;flex-direction:column;align-items:flex-start;">
      <div class="side-panel" style="margin-bottom:18px;">
        <h3>设置</h3>
        <button id="toggle-monster-record-btn" class="export-btn" style="margin-bottom:10px;">隐藏降妖谱</button>
      </div>
      <!-- 时间段统计框 -->
      <div class="side-panel" style="margin-bottom:18px;">
        <h3>今日时间段统计</h3>
        <div id="hourly-stats" style="font-size:14px;line-height:1.8;">
          <!-- 动态生成时间段统计 -->
        </div>
      </div>
      <!-- 时间差分析框 -->
      <div class="side-panel" style="margin-bottom:18px;">
        <h3>今日时间差分析</h3>
        <div style="margin-bottom:10px;">
          <button onclick="toggleTimeGapView()" id="time-gap-toggle-btn" style="padding:4px 12px;font-size:13px;background:#f0f7ff;border:1px solid #2d8cf0;border-radius:4px;cursor:pointer;">显示时间轴</button>
        </div>
        <div id="time-gap-stats" style="font-size:13px;line-height:1.6;">
          <!-- 动态生成时间差统计 -->
        </div>
      </div>
      <div class="side-panel">
        <h3>历史数据与操作记录</h3>
        <ul class="history-list" id="history-list"></ul>
        <button class="export-btn" onclick="exportJson()">导出全部JSON</button>
      </div>
    </div>
  </div>
  <div
    style="position:fixed;right:18px;bottom:12px;z-index:9999;pointer-events:none;opacity:0.18;font-size:32px;font-weight:bold;color:#2d8cf0;user-select:none;letter-spacing:6px;">
    情歌专用</div>
  <!-- 操作记录框 -->
  <div id="op-log-box" style="position:fixed;right:24px;bottom:60px;z-index:9999;min-width:260px;max-width:340px;background:rgba(45,140,240,0.13);border-radius:10px;padding:12px 12px 8px 12px;box-shadow:0 2px 8px rgba(0,0,0,0.10);font-size:15px;color:#333;backdrop-filter:blur(2px);pointer-events:auto;">
    <div style="font-weight:bold;color:#2d8cf0;margin-bottom:6px;font-size:15px;">操作记录</div>
    <div id="op-log-list-wrap" style="height:120px;overflow-y:scroll;background:transparent;margin:0;padding:0;">
      <ul id="op-log-list" style="list-style:none;padding:0;margin:0;"></ul>
    </div>
    <button id="export-oplog-btn" class="export-btn" style="margin-top:8px;font-size:13px;padding:4px 12px;" onclick="exportTodayOpLog()">导出今日操作</button>
  </div>
  <style>
    #op-log-list-wrap::-webkit-scrollbar {
      width: 6px;
      background: #e6f4ff;
      border-radius: 3px;
    }
    #op-log-list-wrap::-webkit-scrollbar-thumb {
      background: #2d8cf0;
      border-radius: 3px;
    }
    #op-log-list li {
      line-height: 1.4;
      font-size: 13px;
      margin-bottom: 2px;
    }
  </style>


  <script src="avatarBase64.js"></script>
  <script>
    // 静态场景和怪物数据，方便扩展
    const sceneMonsterData = {
      "beijuluzhou": {
        name: "北俱芦洲",
        level: "80级",
        monsters: ["远古雾中仙", "远古芙蓉仙子", "远古净瓶女娲", "远古律法女娲", "远古灵符女娲"],
        variant: "北俱变异妖"
      },
      "qilinshan": {
        name: "麒麟山",
        level: "80级",
        monsters: ["远古野猪精", "远古阴阳伞", "远古百足将军", "远古锦毛貂精", "远古鼠先锋"],
        variant: "麒麟变异妖"
      },
      "penglaixiandao": {
        name: "蓬莱仙岛",
        level: "120级",
        monsters: ["远古噬天虎", "远古红萼仙子", "远古踏云兽", "远古夜罗刹", "远古灵鹤"],
        variant: "蓬莱变异妖"
      },
      "wanzishan": {
        name: "碗子山",
        level: "130级",
        monsters: ["远古混沌兽", "远古葫芦宝贝", "远古蝎子精", "远古猫灵", "远古狂豹"],
        variant: "碗子山变异妖"
      },
      "liulinpo": {
        name: "柳林坡",
        level: "160级",
        monsters: ["远古藤蔓妖花", "远古巴蛇", "远古连弩车", "远古机关鸟", "远古机关兽"],
        variant: "柳林坡变异妖"
      },
      "biqiu": {
        name: "比丘国",
        level: "160级",
        monsters: ["远古蜃气妖", "远古曼珠沙华", "远古金身罗汉", "远古修罗傀儡妖", "远古修罗傀儡鬼"],
        variant: "比丘国变异妖"
      }
    };
    
    const sceneList = Object.keys(sceneMonsterData).map(key => ({
      key,
      name: sceneMonsterData[key].name,
      level: sceneMonsterData[key].level,
      monsters: sceneMonsterData[key].monsters,
      variant: sceneMonsterData[key].variant
    }));
    const counts = {};
    function getTodayKey() {
      const now = new Date();
      const year = now.getFullYear();
      const month = String(now.getMonth() + 1).padStart(2, '0');
      const day = String(now.getDate()).padStart(2, '0');
      return `${year}-${month}-${day}`;
    }

    // 初始化counts为localStorage当天数据或0
    const todayData = (() => {
      try {
        return JSON.parse(localStorage.getItem(getTodayKey()) || '{}');
      } catch { return {}; }
    })();
    sceneList.forEach(scene => {
      counts[scene.key] = [];
      // 普通怪
      for (let i = 0; i < scene.monsters.length; i++) {
        counts[scene.key][i] = (todayData[scene.key] && todayData[scene.key][scene.monsters[i]]) || 0;
      }
      // 变异妖
      if (scene.variant) {
        const i = scene.monsters.length;
        counts[scene.key][i] = (todayData[scene.key] && todayData[scene.key][scene.variant]) || 0;
      }
    });

    // 从localStorage加载数据
    function loadData() {
      const data = localStorage.getItem(getTodayKey());
      let obj = {};
      if (data) {
        try {
          obj = JSON.parse(data);
        } catch (e) { obj = {}; }
      }
      sceneList.forEach(scene => {
        // 普通怪
        for (let i = 0; i < scene.monsters.length; i++) {
          counts[scene.key][i] = (obj[scene.key] && obj[scene.key][scene.monsters[i]]) || 0;
          document.getElementById(`count-${scene.key}-${i}`).innerText = counts[scene.key][i];
        }
        // 变异妖
        if (scene.variant) {
          const i = scene.monsters.length;
          counts[scene.key][i] = (obj[scene.key] && obj[scene.key][scene.variant]) || 0;
          document.getElementById(`count-${scene.key}-${i}`).innerText = counts[scene.key][i];
        }
        updateTotal(scene.key);
      });
      updateJsonView();
      // 不再在这里调用setMonsterRecordColVisible
    }

    function saveData() {
      const obj = {};
      let allZero = true;
      sceneList.forEach(scene => {
        obj[scene.key] = {};
        // 普通怪
        for (let i = 0; i < scene.monsters.length; i++) {
          obj[scene.key][scene.monsters[i]] = counts[scene.key][i];
          if (counts[scene.key][i] > 0) allZero = false;
        }
        // 变异妖
        if (scene.variant) {
          const i = scene.monsters.length;
          obj[scene.key][scene.variant] = counts[scene.key][i];
          if (counts[scene.key][i] > 0) allZero = false;
        }
      });
      if (allZero) {
        localStorage.removeItem(getTodayKey()); // 全为0则删除当天key
      } else {
        localStorage.setItem(getTodayKey(), JSON.stringify(obj, null, 2));
      }
      updateJsonView();
    }

    function updateTotal(sceneKey) {
      const total = counts[sceneKey].reduce((a, b) => a + b, 0);
      document.getElementById(`total-count-${sceneKey}`).innerText = '合计：' + total;
    }

    function updateJsonView() {
      // 展示所有历史数据，包括操作记录和时间差分析
      const list = document.getElementById('history-list');
      list.innerHTML = '';

      // 获取所有日期（封妖数据和操作记录）
      const dataKeys = Object.keys(localStorage).filter(k => /^\d{4}-\d{2}-\d{2}$/.test(k));
      const opLogArr = JSON.parse(localStorage.getItem('opLogArr') || '[]');
      const opLogDates = [...new Set(opLogArr.map(item => item.date))];
      const allDates = [...new Set([...dataKeys, ...opLogDates])].sort().reverse();

      allDates.forEach(dateKey => {
        // 获取封妖数据
        const data = localStorage.getItem(dateKey);
        let obj = {};
        if (data) {
          try { obj = JSON.parse(data); } catch (e) { obj = {}; }
        }

        // 获取操作记录
        const dayOpLogs = opLogArr.filter(item => item.date === dateKey);

        // 检查是否有数据
        let hasCountData = false;
        sceneList.forEach(scene => {
          if (obj[scene.key]) {
            for (const v of Object.values(obj[scene.key])) {
              if (Number(v) > 0) hasCountData = true;
            }
          }
        });

        if (!hasCountData && dayOpLogs.length === 0) return; // 没有任何数据则不显示

        const li = document.createElement('li');
        let total = 0;
        sceneList.forEach(scene => {
          if (obj[scene.key]) {
            for (const v of Object.values(obj[scene.key])) total += Number(v) || 0;
          }
        });

        // 计算操作记录统计
        const plusOps = dayOpLogs.filter(item => item.op === '+').length;
        const minusOps = dayOpLogs.filter(item => item.op === '-').length;
        const opSummary = dayOpLogs.length > 0 ? ` | 操作：+${plusOps}/-${minusOps}` : '';

        li.innerHTML = `
          <div class="history-date" onclick="toggleHistoryContent(this)">
            <span>${dateKey}</span>
            <span style="font-size:13px;">合计：${total}${opSummary}<span class="arrow">▶</span></span>
          </div>
          <div class="history-content">
            ${renderHistoryCountData(obj)}
            ${renderHistoryOpLogs(dayOpLogs, dateKey)}
          </div>
        `;
        list.appendChild(li);
      });
    }

    function renderHistoryCountData(obj) {
      if (!obj || Object.keys(obj).length === 0) return '';

      return sceneList.map(scene => {
        const sceneObj = obj[scene.key] || {};
        if (!Object.values(sceneObj).some(v => v && v !== 0)) return '';
        return `<div class='scene-title'>场景：${scene.name}</div>` +
          scene.monsters.map((name) => {
            let avatarSrc = getAvatarBase64(name) || `封妖头像/${name}.png`;
            let avatarOnError = getAvatarBase64(name) ? '' : `onerror=\"this.onerror=null;this.src='封妖头像/${name}.jpg'\"`;
            return `<div class='monster-row' style='display:flex;align-items:center;gap:8px;padding:2px 0;border-bottom:1px dashed #e0e0e0;'><img class='monster-avatar' src='${avatarSrc}' alt='${name}' ${avatarOnError} style='width:28px;height:28px;'><span class='monster-name' style='flex:1;text-align:left;'>${name}</span><span style='min-width:24px;text-align:right;'>${sceneObj[name] || 0}</span></div>`;
          }).join('') +
          `${scene.variant ? `<div class='monster-row monster-row-variant'><span class='monster-name'>${scene.variant}</span><span>${typeof sceneObj[scene.variant] === 'undefined' ? 0 : sceneObj[scene.variant]}</span></div>` : ''}` +
          `<div style="text-align:right;margin:6px 0 10px 0;"><span style="background:#f6ffed;color:#52c41a;font-weight:bold;padding:2px 12px;border-radius:6px;font-size:13px;">合计：${(() => {
            let sum = 0;
            scene.monsters.forEach(name => { sum += Number(sceneObj[name] || 0); });
            if (scene.variant) sum += Number(sceneObj[scene.variant] || 0);
            return sum;
          })()}</span></div>`
      }).join('');
    }

    function renderHistoryOpLogs(dayOpLogs, dateKey) {
      if (dayOpLogs.length === 0) return '';

      // 过滤和优化操作记录显示
      const effectiveOps = getEffectiveOperations(dayOpLogs);
      const plusLogs = effectiveOps.filter(item => item.op === '+').sort((a, b) => a.time.localeCompare(b.time));
      let timeGapAnalysis = '';

      if (plusLogs.length >= 2) {
        const gaps = [];
        for (let i = 1; i < plusLogs.length; i++) {
          const prevTime = parseTime(plusLogs[i-1].time);
          const currTime = parseTime(plusLogs[i].time);
          const gapSeconds = Math.round((currTime - prevTime) / 1000);
          gaps.push({
            seconds: gapSeconds,
            type: gapSeconds <= 30 ? 'fix' : (gapSeconds <= 300 ? 'normal' : 'rest')
          });
        }

        const fixGaps = gaps.filter(g => g.type === 'fix');
        const normalGaps = gaps.filter(g => g.type === 'normal');
        const restGaps = gaps.filter(g => g.type === 'rest');

        if (normalGaps.length > 0) {
          const normalSeconds = normalGaps.map(g => g.seconds);
          const avgGap = normalSeconds.reduce((a, b) => a + b, 0) / normalSeconds.length;
          const minGap = Math.min(...normalSeconds);
          const maxGap = Math.max(...normalSeconds);

          timeGapAnalysis = `
            <div style="background:#f0f7ff;padding:6px;border-radius:4px;margin:8px 0;font-size:12px;">
              <div style="font-weight:bold;color:#2d8cf0;margin-bottom:3px;">时间差分析</div>
              <div>有效间隔${normalGaps.length}次 | 平均${formatGapWithSeconds(avgGap)} | 最短${formatGapWithSeconds(minGap)} | 最长${formatGapWithSeconds(maxGap)}</div>
              <div>修复操作${fixGaps.length}次 | 正常封妖${normalGaps.length}次 | 休息时间${restGaps.length}次</div>
            </div>
          `;
        }
      }

      const originalCount = dayOpLogs.length;
      const effectiveCount = effectiveOps.length;
      const filteredInfo = originalCount > effectiveCount ? ` (已过滤${originalCount - effectiveCount}条无效操作)` : '';

      return `
        <div class='scene-title'>操作记录 (${effectiveCount}条有效${filteredInfo})</div>
        ${timeGapAnalysis}
        <div style="max-height:150px;overflow-y:auto;background:#f8fafd;padding:6px;border-radius:4px;margin:4px 0;">
          ${effectiveOps.slice(0, 20).map(item => {
            let opStr = '';
            if (item.op === '+') opStr = '<span style="color:#52c41a;">+1</span>';
            else if (item.op === '-') opStr = '<span style="color:#ff7875;">-1</span>';
            else opStr = '<span style="color:#faad14;">清零</span>';

            return `<div style="font-size:12px;margin-bottom:2px;line-height:1.4;">
              <span style="color:#888;">${item.time}</span>
              <span style="color:#2d8cf0;">${item.scene}</span>
              <span style="color:#faad14;">${item.monster}</span>
              ${opStr}
            </div>`;
          }).join('')}
          ${effectiveOps.length > 20 ? `<div style="text-align:center;color:#888;font-size:11px;margin-top:4px;">还有${effectiveOps.length - 20}条记录...</div>` : ''}
        </div>
      `;
    }

    // 获取有效操作（过滤掉无意义的+-抵消）
    function getEffectiveOperations(dayOpLogs) {
      // 按时间排序
      const sortedLogs = [...dayOpLogs].sort((a, b) => a.time.localeCompare(b.time));
      const effective = [];

      for (const log of sortedLogs) {
        if (log.op === '+') {
          effective.push(log);
        } else if (log.op === '-') {
          // 查找最近的同一怪物的+1操作
          const lastPlusIndex = effective.findLastIndex(item =>
            item.scene === log.scene &&
            item.monster === log.monster &&
            item.op === '+'
          );

          if (lastPlusIndex !== -1) {
            // 找到了对应的+1，删除它（相当于抵消）
            effective.splice(lastPlusIndex, 1);
          } else {
            // 没找到对应的+1，保留这个-1
            effective.push(log);
          }
        } else {
          // 清零操作直接保留
          effective.push(log);
        }
      }

      // 按时间倒序返回（最新的在前面）
      return effective.sort((a, b) => b.time.localeCompare(a.time));
    }

    // 历史展开状态持久化
    function getHistoryOpenKeys() {
      try { return JSON.parse(localStorage.getItem('historyOpenKeys') || '[]'); } catch { return []; }
    }
    function setHistoryOpenKeys(arr) {
      localStorage.setItem('historyOpenKeys', JSON.stringify(arr));
    }
    window.toggleHistoryContent = function (el) {
      const content = el.parentNode.querySelector('.history-content');
      const arrow = el.querySelector('.arrow');
      const dateKey = el.parentNode.querySelector('.history-date span').innerText;
      let openKeys = getHistoryOpenKeys();
      if (content.classList.contains('active')) {
        content.classList.remove('active');
        arrow.classList.remove('open');
        openKeys = openKeys.filter(k => k !== dateKey);
      } else {
        content.classList.add('active');
        arrow.classList.add('open');
        if (!openKeys.includes(dateKey)) openKeys.push(dateKey);
      }
      setHistoryOpenKeys(openKeys);
    }
    // 渲染历史时恢复展开状态
    const oldUpdateJsonView = updateJsonView;
    updateJsonView = function () {
      oldUpdateJsonView();
      const openKeys = getHistoryOpenKeys();
      document.querySelectorAll('.history-list > li').forEach(li => {
        const dateKey = li.querySelector('.history-date span').innerText;
        const content = li.querySelector('.history-content');
        const arrow = li.querySelector('.arrow');
        if (openKeys.includes(dateKey)) {
          content.classList.add('active');
          arrow.classList.add('open');
        }
      });
    }

    function checkDateAndReload() {
      const nowKey = getTodayKey();
      if (nowKey !== getTodayKey()) {
        location.reload();
        return false;
      }
      return true;
    }

    // 检查日期变更并重置操作记录显示计数
    function checkDateAndResetOpLog() {
      const today = new Date().toISOString().slice(0, 10);
      const lastDate = localStorage.getItem('lastOpLogDate');

      if (lastDate !== today) {
        opLogDisplayCount = 20; // 重置显示计数
        localStorage.setItem('lastOpLogDate', today);
        renderOpLog(); // 重新渲染操作记录
      }
    }
    // 智能操作日志记录
    function addOpLog({sceneKey, monsterName, op, count}) {
      const logArr = JSON.parse(localStorage.getItem('opLogArr') || '[]');
      const now = new Date();
      const timeStr = now.toLocaleTimeString('zh-CN', {hour12: false});
      const dateStr = now.toISOString().slice(0, 10);
      const sceneName = sceneMonsterData[sceneKey]?.name || sceneKey;

      // 如果是-1操作，检查是否可以撤销最近的+1操作
      if (op === '-') {
        // 查找最近5分钟内同一怪物的+1操作
        const fiveMinutesAgo = new Date(now.getTime() - 5 * 60 * 1000);
        const recentPlusIndex = logArr.findIndex(item => {
          if (item.date !== dateStr || item.scene !== sceneName || item.monster !== monsterName || item.op !== '+') {
            return false;
          }
          const itemTime = new Date(`${dateStr} ${item.time}`);
          return itemTime >= fiveMinutesAgo;
        });

        if (recentPlusIndex !== -1) {
          // 找到了可以撤销的+1操作，直接删除它
          logArr.splice(recentPlusIndex, 1);
          localStorage.setItem('opLogArr', JSON.stringify(logArr));
          updateJsonView();
          updateHourlyStats();
          updateTimeGapStats();
          renderOpLog();
          return; // 不添加-1记录
        }
      }

      // 正常添加操作记录
      const monsterCount = Number(count) || 0;
      logArr.unshift({
        time: timeStr,
        date: dateStr,
        scene: sceneName,
        monster: monsterName,
        op,
        count,
        monsterCount
      });

      if (logArr.length > 200) logArr.length = 200;
      localStorage.setItem('opLogArr', JSON.stringify(logArr));
      updateJsonView();
      updateHourlyStats();
      updateTimeGapStats();
      renderOpLog();
    }







    // 时间段统计功能
    function updateHourlyStats() {
      const today = new Date().toISOString().slice(0, 10);
      const logArr = JSON.parse(localStorage.getItem('opLogArr') || '[]');
      const todayLogs = logArr.filter(item => item.date === today);

      // 按时间段统计，基于操作记录计算实际封妖数
      const hourlyData = {};

      todayLogs.forEach(item => {
        if (item.op === '+' || item.op === '-') { // 统计+1和-1操作
          const hour = parseInt(item.time.split(':')[0]);

          if (!hourlyData[hour]) {
            hourlyData[hour] = {};
          }
          if (!hourlyData[hour][item.scene]) {
            hourlyData[hour][item.scene] = 0;
          }

          // +1操作增加计数，-1操作减少计数
          if (item.op === '+') {
            hourlyData[hour][item.scene]++;
          } else if (item.op === '-') {
            hourlyData[hour][item.scene]--;
          }
        }
      });

      // 渲染统计结果
      const statsDiv = document.getElementById('hourly-stats');
      if (!statsDiv) return;

      let html = '';
      const hours = Object.keys(hourlyData).sort((a, b) => parseInt(a) - parseInt(b));

      if (hours.length === 0) {
        html = '<div style="color:#888;font-style:italic;">今日暂无封妖记录</div>';
      } else {
        hours.forEach(hour => {
          const scenes = hourlyData[hour];
          // 只显示有正数封妖数的时间段
          const validScenes = Object.entries(scenes).filter(([scene, count]) => count > 0);

          if (validScenes.length > 0) {
            const totalCount = validScenes.reduce((sum, [scene, count]) => sum + count, 0);

            // 紧凑的一行显示
            const sceneList = validScenes.map(([scene, count]) => `${scene}:${count}`).join(' | ');
            html += `<div style="margin-bottom:3px;padding:4px 6px;background:#f8fafd;border-radius:3px;font-size:13px;line-height:1.4;">`;
            html += `<span style="font-weight:bold;color:#2d8cf0;">${hour}点</span> `;
            html += `<span style="color:#52c41a;font-weight:bold;">封妖数${totalCount}</span> `;
            html += `<span style="color:#666;font-size:12px;">${sceneList}</span>`;
            html += '</div>';
          }
        });

        if (html === '') {
          html = '<div style="color:#888;font-style:italic;">今日暂无有效封妖记录</div>';
        }
      }

      statsDiv.innerHTML = html;
    }

    // 操作记录渲染（优化显示）
    function renderOpLog() {
      const today = new Date().toISOString().slice(0, 10);
      const logArr = JSON.parse(localStorage.getItem('opLogArr') || '[]');
      const todayLogs = logArr.filter(item => item.date === today);
      const list = document.getElementById('op-log-list');
      if (!list) return;

      if (todayLogs.length === 0) {
        list.innerHTML = '<li style="color:#888;font-style:italic;text-align:center;padding:10px;">今日暂无操作记录</li>';
        return;
      }

      // 只显示最近20条，并添加撤销提示
      const displayLogs = todayLogs.slice(0, 20);
      const now = new Date();

      list.innerHTML = displayLogs.map((item, index) => {
        let opStr = '';
        let extraInfo = '';

        if (item.op === '+') {
          opStr = '<span style="color:#52c41a;">+1</span>';
          // 检查是否可以撤销（最近5分钟内）
          const itemTime = new Date(`${item.date} ${item.time}`);
          const timeDiff = (now - itemTime) / (1000 * 60); // 分钟
          if (timeDiff <= 5) {
            extraInfo = ' <span style="color:#888;font-size:10px;">(可撤销)</span>';
          }
        } else if (item.op === '-') {
          opStr = '<span style="color:#ff7875;">-1</span>';
        } else {
          opStr = '<span style="color:#faad14;">清零</span>';
        }

        return `<li><span style='color:#888;font-size:12px;'>${item.time.slice(0,5)}</span> <span style='color:#2d8cf0;'>${item.scene}</span> <span style='color:#faad14;'>${item.monster}</span> ${opStr}${extraInfo}</li>`;
      }).join('');

      if (todayLogs.length > 20) {
        list.innerHTML += `<li style="text-align:center;color:#888;font-size:11px;margin-top:4px;">还有${todayLogs.length - 20}条记录...</li>`;
      }

      // 添加使用提示
      if (todayLogs.some(item => item.op === '+')) {
        list.innerHTML += `<li style="text-align:center;color:#888;font-size:10px;margin-top:4px;padding:2px;background:#f0f7ff;border-radius:2px;">提示：5分钟内点击-1可撤销+1操作</li>`;
      }
    }

    // 导出今日操作记录
    function exportTodayOpLog() {
      const today = new Date().toISOString().slice(0, 10);
      const logArr = JSON.parse(localStorage.getItem('opLogArr') || '[]');
      const todayLogs = logArr.filter(item => item.date === today);

      if (!todayLogs.length) {
        alert('无今日操作记录');
        return;
      }

      const blob = new Blob([JSON.stringify(todayLogs, null, 2)], { type: 'application/json' });
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = `oplog-${today}.json`;
      a.click();
      URL.revokeObjectURL(a.href);
    }

    // 时间差分析功能
    let timeGapViewMode = getTimeGapViewMode(); // 从localStorage读取状态

    function getTimeGapViewMode() {
      return localStorage.getItem('timeGapViewMode') || 'stats';
    }

    function setTimeGapViewMode(mode) {
      timeGapViewMode = mode;
      localStorage.setItem('timeGapViewMode', mode);
    }

    function updateTimeGapStats() {
      const today = new Date().toISOString().slice(0, 10);
      const logArr = JSON.parse(localStorage.getItem('opLogArr') || '[]');
      const todayLogs = logArr.filter(item => item.date === today && item.op === '+');

      const statsDiv = document.getElementById('time-gap-stats');
      if (!statsDiv) return;

      if (todayLogs.length < 2) {
        statsDiv.innerHTML = '<div style="color:#888;font-style:italic;">需要至少2条封妖记录才能分析时间差</div>';
        return;
      }

      // 按时间排序
      todayLogs.sort((a, b) => a.time.localeCompare(b.time));

      // 计算时间差（精确到秒）
      const gaps = [];
      for (let i = 1; i < todayLogs.length; i++) {
        const prevTime = parseTime(todayLogs[i-1].time);
        const currTime = parseTime(todayLogs[i].time);
        const gapSeconds = (currTime - prevTime) / 1000;
        const actualGap = Math.round(gapSeconds);
        const normalizedGap = normalizeGapSeconds(actualGap);

        gaps.push({
          prevLog: todayLogs[i-1],
          currLog: todayLogs[i],
          gapSeconds: actualGap,
          normalizedGap: normalizedGap,
          gapText: formatGapWithSeconds(gapSeconds),
          gapType: getGapType(actualGap)
        });
      }

      function getGapType(seconds) {
        if (seconds <= 30) return 'fix';
        if (seconds <= 300) return 'normal';
        return 'rest';
      }

      if (timeGapViewMode === 'stats') {
        renderTimeGapStats(gaps, statsDiv);
      } else {
        renderTimeline(todayLogs, gaps, statsDiv);
      }
    }

    function parseTime(timeStr) {
      const [hours, minutes, seconds] = timeStr.split(':').map(Number);
      const date = new Date();
      date.setHours(hours, minutes, seconds, 0);
      return date;
    }

    function formatGap(minutes) {
      if (minutes < 60) {
        return `${Math.round(minutes)}分钟`;
      } else {
        const hours = Math.floor(minutes / 60);
        const mins = Math.round(minutes % 60);
        return mins > 0 ? `${hours}小时${mins}分钟` : `${hours}小时`;
      }
    }

    function formatGapWithSeconds(seconds) {
      if (seconds < 60) {
        return `${Math.round(seconds)}秒`;
      } else if (seconds < 3600) {
        const minutes = Math.floor(seconds / 60);
        const secs = Math.round(seconds % 60);
        return secs > 0 ? `${minutes}分${secs}秒` : `${minutes}分钟`;
      } else {
        const hours = Math.floor(seconds / 3600);
        const minutes = Math.floor((seconds % 3600) / 60);
        const secs = Math.round(seconds % 60);
        let result = `${hours}小时`;
        if (minutes > 0) result += `${minutes}分`;
        if (secs > 0) result += `${secs}秒`;
        return result;
      }
    }

    function getGapClassBySeconds(seconds) {
      if (seconds <= 30) return 'gap-fix';         // ≤30秒：修复操作
      if (seconds <= 300) return 'gap-normal';     // 30秒-5分钟：正常封妖间隔
      return 'gap-rest';                           // >5分钟：休息时间
    }

    function normalizeGapSeconds(seconds) {
      // 5分钟以上的间隔按5分钟计算
      return seconds > 300 ? 300 : seconds;
    }

    function renderTimeGapStats(gaps, container) {
      if (gaps.length === 0) {
        container.innerHTML = '<div style="color:#888;font-style:italic;">暂无时间差数据</div>';
        return;
      }

      // 分类统计
      const fixGaps = gaps.filter(g => g.gapType === 'fix');
      const normalGaps = gaps.filter(g => g.gapType === 'normal');
      const restGaps = gaps.filter(g => g.gapType === 'rest');

      // 只对正常间隔计算统计数据
      if (normalGaps.length === 0) {
        container.innerHTML = '<div style="color:#888;font-style:italic;">暂无有效封妖间隔数据</div>';
        return;
      }

      const normalSeconds = normalGaps.map(g => g.gapSeconds);
      const avgGap = normalSeconds.reduce((a, b) => a + b, 0) / normalSeconds.length;
      const minGap = Math.min(...normalSeconds);
      const maxGap = Math.max(...normalSeconds);

      let html = `
        <div style="background:#f0f7ff;padding:8px;border-radius:4px;margin-bottom:8px;">
          <div style="font-weight:bold;color:#2d8cf0;margin-bottom:6px;font-size:14px;">统计概览</div>
          <div style="margin-bottom:4px;font-size:13px;">有效间隔: <span style="color:#333;font-weight:bold;">${normalGaps.length}次</span></div>
          <div style="margin-bottom:4px;font-size:13px;">平均间隔: <span style="color:#333;font-weight:bold;">${formatGapWithSeconds(avgGap)}</span></div>
          <div style="margin-bottom:4px;font-size:13px;">最短间隔: <span style="color:#52c41a;font-weight:bold;">${formatGapWithSeconds(minGap)}</span></div>
          <div style="font-size:13px;">最长间隔: <span style="color:#ff7875;font-weight:bold;">${formatGapWithSeconds(maxGap)}</span></div>
        </div>
        <div style="background:#f8fafd;padding:8px;border-radius:4px;margin-bottom:8px;">
          <div style="font-weight:bold;color:#2d8cf0;margin-bottom:6px;font-size:14px;">间隔分布</div>
          <div style="margin-bottom:3px;font-size:13px;"><span class="gap-fix">●</span> 修复操作(≤30秒): <span style="font-weight:bold;">${fixGaps.length}次</span></div>
          <div style="margin-bottom:3px;font-size:13px;"><span class="gap-normal">●</span> 正常封妖(30秒-5分钟): <span style="font-weight:bold;">${normalGaps.length}次</span></div>
          <div style="font-size:13px;"><span class="gap-rest">●</span> 休息时间(>5分钟): <span style="font-weight:bold;">${restGaps.length}次</span></div>
        </div>
      `;

      // 显示最近几次间隔
      const recentGaps = gaps.slice(-5).reverse();
      html += `
        <div style="background:#f8fafd;padding:8px;border-radius:4px;">
          <div style="font-weight:bold;color:#2d8cf0;margin-bottom:6px;font-size:14px;">最近间隔</div>
      `;

      recentGaps.forEach(gap => {
        const gapClass = getGapClassBySeconds(gap.gapSeconds);
        let gapTypeText = '';
        if (gap.gapType === 'fix') gapTypeText = '修复';
        else if (gap.gapType === 'normal') gapTypeText = '正常';
        else gapTypeText = '休息';

        html += `<div style="margin-bottom:4px;line-height:1.4;font-size:13px;">
          <span class="${gapClass}" style="font-weight:bold;">${gap.gapText}</span>
          <span style="color:#888;font-size:12px;">${gapTypeText} (${gap.prevLog.time.slice(0,5)}→${gap.currLog.time.slice(0,5)})</span>
        </div>`;
      });

      html += '</div>';

      // 如果有修复操作，添加提示
      if (fixGaps.length > 0) {
        html += `
          <div style="background:#fff7e6;padding:6px;border-radius:4px;font-size:12px;margin-top:8px;border-left:3px solid #faad14;">
            <div style="color:#d48806;font-weight:bold;">💡 提示</div>
            <div style="color:#666;margin-top:2px;">检测到${fixGaps.length}次快速操作(≤30秒)，可能是误操作修复</div>
          </div>
        `;
      }
      container.innerHTML = html;
    }

    function renderTimeline(logs, gaps, container) {
      // 按时间倒序排列（最新的在上面）
      const sortedLogs = [...logs].sort((a, b) => b.time.localeCompare(a.time));

      let html = '<div class="timeline">';

      for (let i = 0; i < sortedLogs.length; i++) {
        const log = sortedLogs[i];
        html += `<div class="timeline-item">
          <span style="color:#2d8cf0;font-weight:bold;">${log.time}</span>
          <span style="color:#faad14;">${log.scene}</span>
          <span style="color:#666;">${log.monster}</span>
        `;

        // 对于倒序显示，需要找到前一个时间点的间隔
        if (i < sortedLogs.length - 1) {
          const prevLog = sortedLogs[i + 1]; // 在倒序中，下一个元素是时间上的前一个
          const gap = gaps.find(g =>
            g.prevLog.time === prevLog.time && g.currLog.time === log.time
          );

          if (gap) {
            const gapClass = getGapClassBySeconds(gap.gapSeconds);
            const gapTypeText = gap.gapType === 'fix' ? '修复' : (gap.gapType === 'normal' ? '正常' : '休息');
            html += `<span class="timeline-gap ${gapClass}">↑ ${gap.gapText} (${gapTypeText})</span>`;
          }
        }

        html += '</div>';
      }

      html += '</div>';
      container.innerHTML = html;
    }

    function toggleTimeGapView() {
      const newMode = timeGapViewMode === 'stats' ? 'timeline' : 'stats';
      setTimeGapViewMode(newMode);
      const btn = document.getElementById('time-gap-toggle-btn');
      if (btn) {
        btn.innerText = timeGapViewMode === 'stats' ? '显示时间轴' : '显示统计';
      }
      updateTimeGapStats();
    }

    // 同步刷新初始数量和目前数量
    function updateInitialAndCurrent(sceneKey, idx, count) {
      const monsterName = sceneList.find(s=>s.key===sceneKey).monsters[idx];
      let recordCount = getMonsterRecordCount(sceneKey, monsterName);
      let initialCount = recordCount + Math.min(9, count);
      let currentCount = recordCount;
      const initialSpan = document.getElementById(`initial-${sceneKey}-${idx}`);
      if (initialSpan) initialSpan.innerText = initialCount;
      const currentSpan = document.getElementById(`current-${sceneKey}-${idx}`);
      if (currentSpan) currentSpan.innerText = currentCount;
    }

    function changeCount(sceneKey, idx, delta) {
      if (!checkDateAndReload()) return;
      // 0点后自动同步降妖谱数量
      syncMonsterRecordFromLastSync();
      // 如果是“-”操作且当前数量为0，则不记录也不变更
      if (delta < 0 && counts[sceneKey][idx] === 0) return;
      const prev = counts[sceneKey][idx];
      counts[sceneKey][idx] += delta;
      if (counts[sceneKey][idx] < 0) counts[sceneKey][idx] = 0;
      const now = counts[sceneKey][idx];
      document.getElementById(`count-${sceneKey}-${idx}`).innerText = now;
      updateTotal(sceneKey);
      saveData();
      // 记录操作日志
      const monsterName = sceneList.find(s=>s.key===sceneKey).monsters[idx] || sceneList.find(s=>s.key===sceneKey).variant;
      addOpLog({sceneKey, monsterName, op: delta>0?'+':'-', count: now});
      // 如果数量变化导致跨越9的临界点，立即重新渲染排序
      if ((prev < 9 && now >= 9) || (prev >= 9 && now < 9)) {
        renderScenes();
        loadData();
      } else {
        // 新增：同步刷新预估数量
        updateInitialAndCurrent(sceneKey, idx, now);
      }
    }

    function resetCount(sceneKey, idx) {
      if (!checkDateAndReload()) return;
      counts[sceneKey][idx] = 0;
      document.getElementById(`count-${sceneKey}-${idx}`).innerText = 0;
      updateTotal(sceneKey);
      saveData();
      // 记录操作日志
      const monsterName = sceneList.find(s=>s.key===sceneKey).monsters[idx] || sceneList.find(s=>s.key===sceneKey).variant;
      addOpLog({sceneKey, monsterName, op: '清零', count: 0});
      // 如果原本>=9，清零后要立即重新渲染排序
      renderScenes();
      loadData();
      // 新增：同步刷新预估数量
      updateInitialAndCurrent(sceneKey, idx, 0);
    }

    function exportJson() {
      // 导出全部历史数据，包括封妖数据和操作记录
      const allData = {};

      // 导出封妖数据
      const keys = Object.keys(localStorage).filter(k => /^\d{4}-\d{2}-\d{2}$/.test(k)).sort();
      keys.forEach(dateKey => {
        try {
          allData[dateKey] = { counts: JSON.parse(localStorage.getItem(dateKey)) };
        } catch (e) {
          allData[dateKey] = { counts: {} };
        }
      });

      // 导出操作记录
      const opLogArr = JSON.parse(localStorage.getItem('opLogArr') || '[]');
      const opLogsByDate = {};
      opLogArr.forEach(item => {
        if (!opLogsByDate[item.date]) {
          opLogsByDate[item.date] = [];
        }
        opLogsByDate[item.date].push(item);
      });

      // 合并数据
      Object.keys(opLogsByDate).forEach(dateKey => {
        if (!allData[dateKey]) {
          allData[dateKey] = { counts: {} };
        }
        allData[dateKey].operations = opLogsByDate[dateKey];
      });

      const blob = new Blob([JSON.stringify(allData, null, 2)], { type: 'application/json' });
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = 'all-data-with-operations.json';
      a.click();
      URL.revokeObjectURL(a.href);
    }

    // 记录已选场景
    function getSelectedScenes() {
      const sel = localStorage.getItem('selectedScenes');
      if (!sel) return [];
      try { return JSON.parse(sel); } catch { return []; }
    }
    function setSelectedScenes(arr) {
      localStorage.setItem('selectedScenes', JSON.stringify(arr));
    }

    // 渲染顶部多选按钮
    function renderSceneSelectors() {
      const selArr = getSelectedScenes();
      const box = document.getElementById('scene-selectors');
      box.innerHTML = '';
      sceneList.forEach(scene => {
        const checked = selArr.includes(scene.key);
        const btn = document.createElement('button');
        btn.innerText = `${scene.name}（${scene.level}）`;
        btn.className = 'scene-selector-btn';
        btn.style.margin = '0 8px 0 0';
        btn.style.background = checked ? '#2d8cf0' : '#f0f7ff';
        btn.style.color = checked ? '#fff' : '#2d8cf0';
        btn.style.border = '1px solid #2d8cf0';
        btn.style.borderRadius = '6px';
        btn.style.padding = '6px 16px';
        btn.style.cursor = 'pointer';
        btn.style.fontSize = '15px';
        btn.style.transition = 'all 0.2s';
        btn.onclick = () => {
          let arr = getSelectedScenes();
          if (arr.includes(scene.key)) {
            arr = arr.filter(k => k !== scene.key);
          } else {
            arr.push(scene.key);
          }
          setSelectedScenes(arr);
          renderSceneSelectors();
          renderScenes();
          loadData();
        };
        box.appendChild(btn);
      });
    }

    // 获取头像base64
    function getAvatarBase64(monsterName) {
      if (window.avatarBase64 && window.avatarBase64[monsterName]) {
        return window.avatarBase64[monsterName];
      }
      return null;
    }

    // 获取降妖谱数量
    function getMonsterRecord() {
      try {
        return JSON.parse(localStorage.getItem('monsterRecord') || '{}');
      } catch { return {}; }
    }
    function setMonsterRecord(obj) {
      localStorage.setItem('monsterRecord', JSON.stringify(obj));
    }
    // 获取某怪物降妖谱数量
    function getMonsterRecordCount(sceneKey, monsterName) {
      const rec = getMonsterRecord();
      return rec[sceneKey]?.[monsterName] || 0;
    }
    // 设置某怪物降妖谱数量
    function setMonsterRecordCount(sceneKey, monsterName, value) {
      const rec = getMonsterRecord();
      if (!rec[sceneKey]) rec[sceneKey] = {};
      rec[sceneKey][monsterName] = value;
      setMonsterRecord(rec);
    }

    // 动态渲染场景和怪物表格
    function renderScenes() {
      const area = document.getElementById('scene-area');
      area.innerHTML = '';
      const selArr = getSelectedScenes();
      const monsterRecordColVisible = localStorage.getItem('monsterRecordColVisible') !== '0';
      sceneList.forEach(scene => {
        if (!selArr.includes(scene.key)) return;
        let html = `<div class="container" id="scene-${scene.key}">
          <h2>场景：${scene.name}<span class='scene-level'>${scene.level}</span><span class='scene-total' id="total-count-${scene.key}">合计：${counts[scene.key].reduce((a, b) => a + b, 0)}</span></h2>
          <table>
            <thead>
              <tr>
                <th rowspan="2">怪物名称</th>
`;
        if (monsterRecordColVisible) {
          html += '                <th colspan="2" class="monster-record-col">降妖谱数量</th>';
        }
        html += '                <th colspan="2">封妖</th>\n              </tr>\n              <tr>';
        if (monsterRecordColVisible) {
          html += '                <th class="monster-record-col">初始</th>\n                <th class="monster-record-col">当前</th>';
        }
        html += '                <th>数量</th>\n                <th>操作</th>\n              </tr>\n            </thead>\n            <tbody>';
        // 普通怪物排序：按数量升序，数量相同保持原顺序，数量>=9的怪物单独放到最后
        let monsterArr = scene.monsters.map((monster, i) => ({
          monster,
          idx: i,
          count: counts[scene.key][i]
        }));
        // 分为未满9和>=9
        let lessArr = monsterArr.filter(m => m.count < 9);
        let nineArr = monsterArr.filter(m => m.count >= 9);
        lessArr.sort((a, b) => a.count - b.count);
        nineArr.sort((a, b) => a.count - b.count);
        [...lessArr, ...nineArr].forEach(({monster, idx, count}) => {
          let avatarSrc = getAvatarBase64(monster) || `封妖头像/${monster}.png`;
          let avatarOnError = getAvatarBase64(monster) ? '' : `onerror=\"this.onerror=null;this.src='封妖头像/${monster}.jpg'\"`;
          // 获取降妖谱数量
          let recordCount = getMonsterRecordCount(scene.key, monster);
          // 初始数量 = 降妖谱数量
          let currentCount = recordCount;
          // 目录数量 = 降妖谱数量 + min(9, 今日数量)
          let initialCount = recordCount + Math.min(9, count);
          html += `<tr${count >= 9 ? ' class=\"monster-row-nine\"' : ''}>\n            <td><span class=\"monster-cell\"><img class=\"monster-avatar\" src=\"${avatarSrc}\" alt=\"${monster}\" ${avatarOnError}><span class=\"monster-name\">${monster}</span></span></td>\n`;
          if (monsterRecordColVisible) {
            html += `<td class=\"monster-record-col\"><input type=\"number\" min=\"0\" value=\"${recordCount}\" style=\"width:56px;\" onchange=\"onMonsterRecordInput('${scene.key}','${monster}',this.value)\"></td>\n`;
            html += `<td class=\"monster-record-col\"><span id=\"initial-${scene.key}-${idx}\">${initialCount}</span></td>\n`;
          }
          html += `<td><span class=\"count\" id=\"count-${scene.key}-${idx}\">${count}</span></td>\n            <td>\n              <button class=\"btn\" onclick=\"changeCount('${scene.key}', ${idx}, -1)\">-</button>\n              <button class=\"btn\" onclick=\"changeCount('${scene.key}', ${idx}, 1)\">+</button>\n            </td>\n          </tr>`;
        });
        // 变异妖
        if (scene.variant) {
          const i = scene.monsters.length;
          let count = counts[scene.key][i];
          html += `<tr class=\"monster-row-variant\">\n            <td><span class=\"monster-name\">${scene.variant}</span></td>\n`;
          if (monsterRecordColVisible) {
            html += `<td class=\"monster-record-col\" colspan=\"2\"></td>\n`;
          }
          html += `<td><span class=\"count\" id=\"count-${scene.key}-${i}\">${count}</span></td>\n            <td>\n              <button class=\"btn\" onclick=\"changeCount('${scene.key}', ${i}, -1)\">-</button>\n              <button class=\"btn\" onclick=\"changeCount('${scene.key}', ${i}, 1)\">+</button>\n            </td>\n          </tr>`;
        }
        html += '</tbody></table></div>';
        area.innerHTML += html;
      });
      // 渲染后同步按钮文字
      const btn = document.getElementById('toggle-monster-record-btn');
      if (btn) {
        btn.innerText = monsterRecordColVisible ? '隐藏降妖谱' : '显示降妖谱';
      }
    }
    // 降妖谱数量输入事件
    window.onMonsterRecordInput = function(sceneKey, monsterName, value) {
      let v = parseInt(value, 10);
      if (isNaN(v) || v < 0) v = 0;
      setMonsterRecordCount(sceneKey, monsterName, v);
      renderScenes(); // 重新渲染以刷新预估数量
      loadData();
      // 额外刷新所有本场景的初始数量和目前数量
      const scene = sceneList.find(s=>s.key===sceneKey);
      scene.monsters.forEach((monster, idx) => {
        const count = counts[sceneKey][idx];
        updateInitialAndCurrent(sceneKey, idx, count);
      });
    }
    // 高亮样式
    const style = document.createElement('style');
    style.innerHTML = `.monster-row-nine,\n.monster-row-nine td {\n  background: #fff3d1 !important; color: #b26a00 !important;\n}\n.monster-row-variant,\n.monster-row-variant td {\n  background: #e6f7ff !important; color: #1766b3 !important;\n}`;
    document.head.appendChild(style);

    // 初始化
    // renderSceneSelectors(); // 移至DOMContentLoaded
    // renderScenes(); // 移至DOMContentLoaded
    // setTimeout(() => { // 移至DOMContentLoaded
    //   sceneList.forEach(scene => {
    //     updateTotal(scene.key);
    //   });
    //   updateJsonView();
    // }, 0);



    // 自动同步降妖谱数量为上次同步日至昨天的所有“当前”数量之和
    function syncMonsterRecordFromLastSync() {
      const lastSyncDate = localStorage.getItem('monsterRecordSyncDate');
      const today = getTodayKey();
      // 获取降妖谱原始数据
      let rec = getMonsterRecord();
      // 计算起始日期
      let startDate;
      if (lastSyncDate && /^\d{4}-\d{2}-\d{2}$/.test(lastSyncDate)) {
        startDate = new Date(lastSyncDate);
      } else {
        // 如果没有记录，从今天前一天开始
        startDate = new Date();
        startDate.setDate(startDate.getDate() - 1);
      }
      // 目标日期（不包括今天）
      const endDate = new Date(today);
      // 累加每一天的数据
      let changed = false;
      while (startDate < endDate) {
        const y = startDate.getFullYear();
        const m = String(startDate.getMonth() + 1).padStart(2, '0');
        const d = String(startDate.getDate()).padStart(2, '0');
        const key = `${y}-${m}-${d}`;
        const yData = localStorage.getItem(key);
        if (yData) {
          let yObj;
          try { yObj = JSON.parse(yData); } catch { yObj = {}; }
          sceneList.forEach(scene => {
            if (!rec[scene.key]) rec[scene.key] = {};
            scene.monsters.forEach(monster => {
              const addVal = (yObj[scene.key] && yObj[scene.key][monster]) || 0;
              rec[scene.key][monster] = (rec[scene.key][monster] || 0) + addVal;
              if (addVal > 0) changed = true;
            });
          });
        }
        startDate.setDate(startDate.getDate() + 1);
      }
      if (changed) setMonsterRecord(rec);
      localStorage.setItem('monsterRecordSyncDate', today);
      // 不要在这里直接刷新页面，否则会导致按钮失效或死循环
      // renderScenes();
      // loadData();
    }
    // 页面加载和按钮事件绑定
    document.addEventListener('DOMContentLoaded', function() {
      const btn = document.getElementById('toggle-monster-record-btn');
      if (btn) {
        btn.onclick = function() {
          const visible = localStorage.getItem('monsterRecordColVisible') !== '0';
          // 只切换localStorage和按钮文字，然后重新渲染
          localStorage.setItem('monsterRecordColVisible', visible ? '0' : '1');
          renderScenes();
          loadData();
          btn.innerText = !visible ? '隐藏降妖谱' : '显示降妖谱';
        };
      }
      // 页面加载时自动同步和渲染
      syncMonsterRecordFromLastSync();
      renderSceneSelectors();
      renderScenes();
      loadData();
      setTimeout(() => {
        sceneList.forEach(scene => {
          updateTotal(scene.key);
        });
        updateJsonView();
        updateHourlyStats(); // 初始化时间段统计
        updateTimeGapStats(); // 初始化时间差统计
        renderOpLog(); // 初始化操作记录

        // 初始化时间差分析按钮状态
        const btn = document.getElementById('time-gap-toggle-btn');
        if (btn) {
          btn.innerText = timeGapViewMode === 'stats' ? '显示时间轴' : '显示统计';
        }
        // 统一在所有渲染和数据刷新后，最后调用一次
        const visible = localStorage.getItem('monsterRecordColVisible') !== '0';
        // setMonsterRecordColVisible(visible); // 移除此行
      }, 0);
    });
  </script>
</body>

</html>